﻿using System.Linq;
using System.Collections.Generic;
using System;
using Citi.Scheduler.Domain.Utils;
using System.Data.Objects;
using Citi.Helpers;

namespace Citi.Scheduler.Domain
{
    public partial class Machine
    {
        public const string ServiceExecutionName = "Citi Scheduler Execution Service";
        public const string ServiceMonitorName = "Citi Scheduler Monitor Service";
        public const string ServiceSchedulerName = "Citi Scheduler Service";

        public Machine GetByHostName(string hostName)
        {
            return SelectAllActive<Machine>().FirstOrDefault(x => x.HostName.ToUpper() == hostName.ToUpper());
        }

        public Machine GetByHostName(string hostName, MachineCenter machineCenter)
        {
            var machine = SelectAllActive<Machine>().FirstOrDefault(x => x.HostName.ToUpper() == hostName.ToUpper());

            if (machine == null) return null;

            machine = machine.SelectMachineByType(machine, machineCenter);

            return machine;
        }

        public RoutineExecution RoutineInProgress
        {
            get
            {
                var routineId = GetRunningRoutine(Id);

                if (routineId == 0) return null;

                return SelectById<RoutineExecution>(routineId);
            //    return RoutineExecutions.Where(x => x.InProgress && x.EndsOn == null && x.StartsOn != null
            //                        && DateTime.Now <= x.StartsOn.Value.AddMinutes((x.Routine.EstimatedTime + x.Routine.EstimatedTime * x.Routine.PercentageAcceptableVariation / 100) + 5))
            //                        .OrderByDescending(x => x.StartsOn).FirstOrDefault();
            }
        }

        private Machine SelectMachineByType(Machine machine, MachineCenter machineCenter)
        {
            switch (machineCenter)
            {
                case MachineCenter.None:
                    return machine;
                case MachineCenter.Execution:
                    return machine.ExecutionCenter ? machine : null;
                case MachineCenter.Scheduler:
                    return machine.SchedulerCenter ? machine : null;
                case MachineCenter.Monitor:
                    return machine.MonitorCenter ? machine : null;
            }

            return null;
        }

        public IEnumerable<Machine> SelectByTypeCenter(MachineCenter machineCenter)
        {
            //return SelectAll<Machine>();
            return SelectAll<Machine>().Select(x => SelectMachineByType(x, machineCenter)).Where(x => x != null);
        }

        public IEnumerable<Machine> SelectByRoutineConfigurations(int routineId)
        {
            var machines = new Machine().SelectByTypeCenter(MachineCenter.Execution);
            var machinesExecute = new Machine().SelectByTypeCenter(MachineCenter.Execution).ToList();
            var requisites = new RoutineRequisite().SelectByRoutineId(routineId);
            var configurationGroups = requisites.Select(x => x.Configuration.ConfigurationGroupId);

            foreach (var configurationGroup in configurationGroups)
            {
                var requisitesByGroup = requisites.Where(x => x.Configuration.ConfigurationGroupId == configurationGroup).Select(x => x.ConfigurationId);

                foreach (var machine in machines)
                {
                    var machineConfigurationById = machine.MachineConfigurations
                        .Where(x => x.Configuration.ConfigurationGroupId == configurationGroup)
                        .Select(x => x.ConfigurationId);

                    //if (machineConfigurationById.All(requisitesByGroup.Contains))
                    if (!machineConfigurationById.Where(requisitesByGroup.Contains).Any())
                        machinesExecute.RemoveAll(x => x.Id == machine.Id);
                }

                //machines = machines.Where(x =>requisitesByGroup.Contains
                //            (x.MachineConfigurations.Where(y => y.Configuration.ConfigurationGroupId == configurationGroup)
                //             .Select(y => y.ConfigurationId)));
            }

            return machinesExecute;
        }

        public IEnumerable<Machine> SelectByCenterBackupOrder(MachineCenter machineCenter)
        {
            return SelectByTypeCenter(machineCenter).OrderBy(x => x.BackupPosition);
        }

        public int GetRunningRoutine(int machineId)
        {
            var query = string.Format(@"SELECT RoutineExecution.Id FROM RoutineExecution
	                            INNER JOIN Routine ON Routine.Id = RoutineId
                            WHERE EndsOn IS NULL AND StartsOn IS NOT NULL
	                            AND GetDate() <= DATEADD(mi, (EstimatedTime + EstimatedTime * PercentageAcceptableVariation / 100) + 5, StartsOn)
	                            AND MachineId = {0}", machineId);

            var datatable = SqlHelper.ExecuteReader(query, ConnectionString, 3000);

            return datatable.Rows.Count > 0 ? int.Parse(datatable.Rows[0][0].ToString()) : 0;
        }

        public bool IsRunningRoutine(int machineId)
        {
            var routineId = GetRunningRoutine(machineId);

            return routineId > 0;
        }
    }
}
